package com.javacommunity.model.dao.impl;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.javacommunity.hibernate.HibernateUtil;
import com.javacommunity.model.dao.AnswerVotationDAO;
import com.javacommunity.model.entity.Answer;
import com.javacommunity.model.entity.User;
import com.javacommunity.model.entity.UserAnswer;

public class AnswerVotationDAOImpl implements AnswerVotationDAO {

	private static AnswerVotationDAOImpl answerVotationDAO;

	public static AnswerVotationDAOImpl getInstance() {
		if (answerVotationDAO == null) {
			answerVotationDAO = new AnswerVotationDAOImpl();
		}
		return answerVotationDAO;
	}

	private Session session = null;

	@Override
	public boolean isVote(User user, Answer answer) {
		boolean isCheck = false;

		session = HibernateUtil.getSessionFactory().openSession();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			String sql = "FROM UserAnswer as u WHERE u.user = ? and u.answer=?";
			Query query = session.createQuery(sql);
			query.setParameter(0, user);
			query.setParameter(1, answer);
			if (query.list() != null && query.list().size() > 0) {
				isCheck = true;
			}
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null) {
				tx.rollback();
			}
			e.printStackTrace();
			isCheck = false;
		} finally {
			if (session != null)
				session.close();
		}
		return isCheck;
	}

	@Override
	public boolean voteUp(User user, Answer answer) {
		Transaction tx = null;
		try {
			if (isVote(user, answer)) {
				session = HibernateUtil.getSessionFactory().openSession();
				tx = session.beginTransaction();
				Query query = session
						.createQuery("Update UserAnswer up Set up.vote = true where user=? and answer=?");
				query.setParameter(0, user);
				query.setParameter(1, answer);
				query.executeUpdate();
				tx.commit();
				return true;
			} else {
				session = HibernateUtil.getSessionFactory().openSession();
				tx = session.beginTransaction();
				UserAnswer userAnswer = new UserAnswer(answer, user, true);
				session.save(userAnswer);
				tx.commit();
				return true;
			}
		} catch (Exception e) {
			if (tx != null) {
				tx.rollback();
			}
			e.printStackTrace();
			return false;
		} finally {
			if (session != null)
				session.close();
		}
	}

	@Override
	public boolean voteDown(User user, Answer answer) {
		Transaction tx = null;
		try {
			if (isVote(user, answer)) {
				session = HibernateUtil.getSessionFactory().openSession();
				tx = session.beginTransaction();
				Query query = session
						.createQuery("Update UserAnswer up Set up.vote = false where user=? and answer=?");
				query.setParameter(0, user);
				query.setParameter(1, answer);
				query.executeUpdate();
				tx.commit();
				return true;
			} else {
				session = HibernateUtil.getSessionFactory().openSession();
				tx = session.beginTransaction();
				UserAnswer userAnswer = new UserAnswer(answer, user, false);
				session.save(userAnswer);
				tx.commit();
				return true;
			}
		} catch (Exception e) {
			if (tx != null) {
				tx.rollback();
			}
			e.printStackTrace();
			return false;
		} finally {
			if (session != null)
				session.close();
		}
	}

	@Override
	public int countVotation(Answer answer) {
		int count = 0;
		Transaction tx = null;
		session = HibernateUtil.getSessionFactory().openSession();
		try {
			tx = session.beginTransaction();
			int countVoteUp = session
					.createQuery(
							"From UserAnswer up Where up.answer = ? and up.vote = true")
					.setParameter(0, answer).list().size();
			int countVoteDown = session
					.createQuery(
							"From UserAnswer up Where up.answer = ? and up.vote = false")
					.setParameter(0, answer).list().size();
			tx.commit();
			count = countVoteUp - countVoteDown;
		} catch (HibernateException e) {
			if (tx != null) {
				tx.rollback();
			}
			e.printStackTrace();
		} finally {
			if (session != null)
				session.close();
		}
		return count;
	}


}
